import QtQuick

/*
  图案密码控件

  通过width,height指定控件的宽高。row,column指定图案密码的行数和列数。网格宽=width/column,网格高=height/row。
  通过hotRadius指定网格中圆圈的半径，单位像素。半径以内可以吸附线。、
  lineWidth指定线宽，单位像素。
  [signal] released() 图案松开信号，通过selectIndexs获取选中的点。index从0开始，从左到右依次+1。
*/
Item {
    id: root

    property int row: 4                                             //网格行数
    property int column: 4                                          //网格列数
    property int pressedIndex: -1                                   //鼠标按到了某个网格的热区内
    property var selectIndexs: []                                   //鼠标滑过选中的点
    property int lineWidth: 6                                       //连线宽度，圆圈线宽
    property int hotRadius: Math.min(cellWidth,cellHeight) * 0.2    //热区半径，半径之内点会被选中
    property color color: "white"                                   //圆圈颜色
    property color borderColor: "darkGray"                          //默认圆圈边框颜色
    property color selectedBorderColor: "gray"                      //选中圆圈边框颜色
    property color lineColor: "gray"                                //连线颜色
    readonly property alias pressed: mouseArea.pressed              //网格中有鼠标按下
    readonly property alias cellWidth: gridView.cellWidth           //网格宽度
    readonly property alias cellHeight: gridView.cellHeight         //网格高度

    signal released()                                               //图案松开

    //绘制选中点之间的连线
    Canvas{
        id: canvas
        anchors.fill: parent

        onPaint: {
            var ctx = getContext("2d")
            ctx.lineJoin = 'round';
            ctx.clearRect(0,0,canvas.width,canvas.height)

            if(0 === selectIndexs.length)
                return ;

            ctx.strokeStyle = root.lineColor
            ctx.lineWidth = lineWidth

            for(var i = 0; i < root.selectIndexs.length; i++) {
                var posX = (Math.floor(selectIndexs[i] % column) + 0.5) * cellWidth
                var posY = (Math.floor(selectIndexs[i] / column) + 0.5) * cellHeight
                if(0 === i){
                    ctx.beginPath()
                    ctx.moveTo(posX, posY)
                }else{
                    ctx.lineTo(posX, posY)
                }
            }

            ctx.lineTo(mouseArea.mouseX, mouseArea.mouseY)
            ctx.stroke()
        }


    }

    //图案网格圈显示
    GridView{
        id: gridView
        anchors.fill: parent
        cellHeight: gridView.height / row
        cellWidth: gridView.width / column
        interactive: false
        model: row * column
        delegate: Item{
            property bool checked: root.pressed ? (pressedIndex === index? true : checked) : false

            width: gridView.cellWidth
            height: gridView.cellHeight

            Rectangle{
                anchors.centerIn: parent
                width: hotRadius * 2
                height: width
                border.width: lineWidth
                border.color: checked ?  root.selectedBorderColor : root.borderColor
                color: root.color
                radius: width / 2
            }
        }
    }

    //检测选中点模型管理
    MouseArea{
        id: mouseArea

        anchors.fill: parent
        onPressedChanged: refresh()
        onMouseXChanged: refresh()
        onMouseYChanged: refresh()

        function refresh(){
            if (!pressed || mouseX >= width || mouseY >= height
                    || mouseX < 0 ||  mouseY < 0){
                canvas.requestPaint()
                return
            }
            //找到光标所在的格子
            var mouseRow = Math.floor(mouseY / cellHeight)
            var mouseColumn = Math.floor(mouseX / cellWidth)

            //坐标转换 以当前格子中心点为0,0点
            var newPosX = mouseX - (mouseColumn + 0.5) * cellWidth
            var newPosY = mouseY - (mouseRow + 0.5) * cellHeight

            //计算与原点的距离，判断是否在圆形热区中
            var distance = Math.sqrt(newPosX * newPosX + newPosY * newPosY);
            if (distance < hotRadius) {
                //计算热区的index，添加选中
                var index = mouseRow * root.column + mouseColumn
                if(-1 === selectIndexs.indexOf(index)) {
                    selectIndexs.push(index)
                    pressedIndex = index
                }
            }else{
                pressedIndex = -1
            }

            //重绘连线
            canvas.requestPaint()
        }

        onPressed: selectIndexs = []
        onReleased: {
            root.released()
            selectIndexs = []
        }
    }
}
